package com.yuesystem.interceptor;

import com.alibaba.fastjson.JSONObject;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.yuesystem.common.BaseContext;
import com.yuesystem.common.R;
import com.yuesystem.dto.UserSimple;
import com.yuesystem.service.impl.CollectItemServiceImpl;
import com.yuesystem.service.impl.FeedbackServiceImpl;
import com.yuesystem.util.JwtUtil;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;



/**
 * 拦截需要授权的接口.
 */
@Slf4j
@Component
public class PermisssionInterceptor implements HandlerInterceptor {
  
  // 目标方法执行前调用
  @Override
  public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
      throws IOException {
    // 如果请求为 OPTIONS 请求，则返回 true,否则需要通过jwt验证
    
    if (HttpMethod.OPTIONS.toString().equals(request.getMethod())) {
      log.info("***********OPTIONS请求，放行************");
      System.out.println("OPTIONS请求，放行");
      return true;
    }
    
    // 检查用户JWT
    String jwt = request.getHeader("Authorization");
    
    if (jwt == null) {
      //log.info(jwt.toString());
      log.info("token不存在");
    }
    
    // 校验并取出私有信息
    try {
      // token 解码
      DecodedJWT dj = JwtUtil.decodeToken(jwt);
      // 取出基本用户信息加入请求头 ---------------------------------
      String userId = dj.getClaim("userId").asString();
      log.info("在拦截器中的userId:{}", userId);
      CollectItemServiceImpl.setUserId(Long.valueOf(userId));
      
      String userName = dj.getClaim("userName").asString();
      log.info("在拦截器中的userName：{}", userName);
      
      String status = dj.getClaim("status").asString();
      log.info("在拦截器总的status:{}", status);
      
      // jwt校验合格的，将 jwt 中存的用户信息加入请求头，不合格的，请求头存个空用户
      BaseContext.setCurrentId(Long.valueOf(userId));
      log.info(String.valueOf(BaseContext.getCurrentId()));
      CollectItemServiceImpl.setUserId(BaseContext.getCurrentId());
      FeedbackServiceImpl.setUserId(BaseContext.getCurrentId());
      log.info("测试" + FeedbackServiceImpl.getUserId());
      //CollectItemServiceImpl.getUserId();
      UserSimple userSimple = new UserSimple();
      userSimple.setUserId(Long.valueOf(userId));
      userSimple.setUserName(userName);
      userSimple.setStatus(Integer.parseInt(status));
      BaseContext.setCurrentUser(userSimple);
      //CollectItemServiceImpl.setUserId(1719174824359653378L);
      
      // 计算当前时间是否超过过期时间的一半，如果是就帮用户续签 --------------------------
      // 此处并不是永久续签，只是为 大于过期时间的一半 且 小于过期时间 的 token 续签
      Long expTime = dj.getExpiresAt().getTime();
      Long iatTime = dj.getIssuedAt().getTime();
      Long nowTime = new Date().getTime();
      if ((nowTime - iatTime) > (expTime - iatTime) / 2) {
        // 生成新的jwt
        Map<String, String> payload = new HashMap<>();
        payload.put("userId", userId); // 加入一些非敏感的用户信息
        payload.put("userName", userName);    // 加入一些非敏感的用户信息
        payload.put("status", status);
        String newJwt = JwtUtil.generateToken(payload);
        // 加入返回头
        response.addHeader("Authorization", newJwt);
      }
      return true;
      
    } catch (JWTDecodeException e) {
      log.error("令牌错误");
      
      response.setCharacterEncoding("UTF-8");
      response.setContentType("application/json; charset=utf-8");
      
      PrintWriter writer = response.getWriter();
      writer.write(JSONObject.toJSONString(new R(0, "令牌错误", null, null)));
      writer.flush();
      writer.close();
      return false;
    } catch (TokenExpiredException e) {
      log.error("令牌过期");
      
      response.setCharacterEncoding("UTF-8");
      response.setContentType("application/json; charset=utf-8");
      
      PrintWriter writer = response.getWriter();
      writer.write(JSONObject.toJSONString(new R(0, "令牌过期", null, null)));
      writer.flush();
      writer.close();
      return false;
    }
  }
  
  // 目标方法执行后调用
  @Override
  public void postHandle(HttpServletRequest request, HttpServletResponse response,
                         Object handler, ModelAndView modelAndView) throws Exception {
    HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
  }
  
  // 页面渲染前调用
  @Override
  public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
                              Object handler, Exception ex) throws Exception {
    HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
  }
  
  /**
   * 定义拦截器返回response信息.
   *
   * @param response 状态体
   * @param res 结果
   * @throws IOException 异常信息
   */
  private void addResBody(HttpServletResponse response, R res) throws IOException {
    
    response.setStatus(HttpServletResponse.SC_FORBIDDEN);        // 设置状态码
    response.setCharacterEncoding("UTF-8");
    response.setContentType("application/json; charset=utf-8");
    PrintWriter out = response.getWriter();
    out.write(JSONObject.toJSONString(res));
    out.flush();
    out.close();
  }
  
}